package net.vinote.smart.platform.base;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;

public class ClassExec {
	protected String clazz;

	protected String method;// 方法名

	protected int modifier = 0;// 修饰符对应的编码值

	protected String returnType;// 返回类型

	/** 类路径 */
	public void setClass(String clazz) {
		this.clazz = clazz;
	}

	/** 要执行的方法名 */
	public void setMethod(String method) {
		this.method = method;
	}

	/** 获取传入修饰符对应的编码值 */
	public void setModifier(String[] modifiers) {
		for (int i = 0; i < modifiers.length; i++) {
			String mod = modifiers[i];
			if ("public".equals(mod))
				modifier |= Modifier.PUBLIC;
			if ("protected".equals(mod))
				modifier |= Modifier.PROTECTED;
			if ("private".equals(mod))
				modifier |= Modifier.PRIVATE;
			if ("abstract".equals(mod))
				modifier |= Modifier.ABSTRACT;
			if ("static".equals(mod))
				modifier |= Modifier.STATIC;
			if ("final".equals(mod))
				modifier |= Modifier.FINAL;
			if ("transient".equals(mod))
				modifier |= Modifier.TRANSIENT;
			if ("volatile".equals(mod))
				modifier |= Modifier.VOLATILE;
			if ("synchronized".equals(mod))
				modifier |= Modifier.SYNCHRONIZED;
			if ("native".equals(mod))
				modifier |= Modifier.NATIVE;
			if ("strictfp".equals(mod))
				modifier |= Modifier.STRICT;
			if ("interface".equals(mod))
				modifier |= Modifier.INTERFACE;
		}
	}

	/**
	 * 要执行方法的返回类型, 暂时只支持基本类型
	 **/
	public void setReturnType(String returnType) {
		this.returnType = returnType;
	}

	/**
	 * 执行类方法
	 * 
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 **/
	public Object exeMethod(Object... params) throws IllegalArgumentException,
			InvocationTargetException {
		Object clazz;
		try {
			clazz = Class.forName(this.clazz).newInstance();
			Method[] methods = clazz.getClass().getMethods();
			int i = 0;
			for (; i < methods.length; i++) {
				Method m = methods[i];
				if (m.getModifiers() != modifier)
					continue;
				if (!m.getReturnType().getSimpleName().equals(returnType))
					continue;
				if (!m.getName().equals(method))
					continue;
				if (!isSameType(m.getParameterTypes(), params))
					continue;
				return m.invoke(clazz, params);
			}
			if (i >= methods.length) {
				throw new RuntimeException("Method  "
						+ Modifier.toString(modifier) + " " + returnType + " "
						+ method + "(" + paramType(params)
						+ ") is not in class" + this.clazz);
			}
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 参数类型是否一致 , 只能支持简单类型 注：此方法可能存在问题
	 **/
	private boolean isSameType(Type[] type, Object[] paramTypes) {
		if ((paramTypes == null || paramTypes.length == 0)
				&& (type == null || type.length == 0))
			return true;
		if (paramTypes.length == type.length) {
			for (int i = 0; i < type.length; i++) {
				if (!ignoreBasicType(
						(type[i] instanceof Class) ? getTypeName((Class<?>) type[i])
								: type[i].toString(),
						(paramTypes[i] instanceof Class) ? getTypeName((Class<?>) paramTypes[i])
								: paramTypes[i].getClass().getSimpleName()))
					return false;
			}
			return true;
		}
		return false;
	}

	String getTypeName(Class<?> type) {
		if (type.isArray()) {
			try {
				Class<?> cl = type;
				int dimensions = 0;
				while (cl.isArray()) {
					dimensions++;
					cl = cl.getComponentType();
				}
				StringBuffer sb = new StringBuffer();
				sb.append(cl.getSimpleName());
				for (int i = 0; i < dimensions; i++) {
					sb.append("[]");
				}
				return sb.toString();
			} catch (Throwable e) { /* FALLTHRU */
			}
		}
		return type.getSimpleName();
	}

	/**
	 * 类型名比较，忽略基本数据类型
	 **/
	private boolean ignoreBasicType(String parm1, String parm2) {
		if ("Float".equals(parm1))
			parm1 = "float";
		if ("Integer".equals(parm1))
			parm1 = "int";
		if ("Boolean".equals(parm1))
			parm1 = "boolean";
		if ("Byte".equals(parm1))
			parm1 = "byte";
		if ("Character".equals(parm1))
			parm1 = "char";
		if ("Long".equals(parm1))
			parm1 = "long";
		if ("Short".equals(parm1))
			parm1 = "short";
		if ("Double".equals(parm1))
			parm1 = "double";

		if ("Float".equals(parm2))
			parm2 = "float";
		if ("Integer".equals(parm2))
			parm2 = "int";
		if ("Boolean".equals(parm2))
			parm2 = "boolean";
		if ("Byte".equals(parm2))
			parm2 = "byte";
		if ("Character".equals(parm2))
			parm2 = "char";
		if ("Long".equals(parm2))
			parm2 = "long";
		if ("Short".equals(parm2))
			parm2 = "short";
		if ("Double".equals(parm2))
			parm2 = "double";
		return parm1.equals(parm2);
	}

	/** 输入参数的类型 */
	private String paramType(Object[] params) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < params.length; i++) {
			sb.append(params[i].toString());
			if (i < params.length - 1) {
				sb.append(",");
			}
		}
		return sb.toString();
	}
}
